// const Scope = require('./scope')
// const walk = require('./walk')
import Scope from './scope.js';
import walk from './walk.js';
//找出当前模块使用了那些变量，那些是导入的，那些是自己的
export default function analyse(ast,magicString,module){
  let scope = new Scope({name:module.path});
  ast.body.forEach(statement => {
    function addToScope(declaration){
      
      // let Variable;
      if(declaration.id.name){
        scope.add(declaration.id.name);
        if(!scope.parent){
          //当前模块顶级作用域
          statement._defines[declaration.id.name] = true;
        }
      }else if(declaration.id.type ==='ObjectPattern'){
        declaration.id.properties.forEach(Property=>{
          scope.add(Property.value.name)
          if(!scope.parent){
            //当前模块顶级作用域
            statement._defines[Property.value.name] = true;
          }
        })
      }
      
    }
    // statement._source ={value:magicString.snip(statement.start,statement.end)}
    let codeString = magicString.snip(statement.start,statement.end);
    Object.defineProperties(statement,{
      //当前模块定义的所有变量
      // _defines:{value:{}},
      //当前模块依赖的外部变量
      // _dependsOn:{value:{}},
      //已经存在/打包过的变量  多次引用的
      // _included:{weitable:true,value:{}},
      _source:{value:codeString},
      // 修改的变量
      // _modifies: {value: {},},
      // _funDefine: {value: {},},
      //测试用
      // _code:{value:codeString.toString()}

    })
    statement._included = false;
    statement._code = codeString.toString()
    statement._defines={},
    statement._dependsOn={},
    statement._modifies= {},
    statement._funDefine= {},
    
    //创建作用域链
    walk(statement,{
      enter(node,parentNode){
        
        let newScope;
        function fun(funNode){
          const params = []
          funNode.params.forEach((item)=>{
            if(item.type ==='Identifier'){
              params.push(item.name);
            }else if(item.type ==='ObjectPattern'){
              let arr =  item.properties.map(obj=>{
                return obj.value.name;
              });
              params.push(...arr)
            }else if(item.type==='AssignmentPattern'){
              // console.log(item);
              params.push(item.left.name)
            }
          })
          // if(funNode.id.name==='build')console.log(params);
          addToScope(funNode);
          
          //如果是一个函数声明，夫作用域就是当前作用域
          newScope = new Scope({
            name:funNode.id.name,
            parent:scope,
            params,
          })
        }
        switch(node.type){
          case 'FunctionDeclaration':
            fun(node)
            break;
          case 'FunctionExpression': 
            node.id = parentNode.key || parentNode.id
            fun(node)
            break;
          case 'ArrowFunctionExpression': 
            node.id = {name:'ArrowFunctionExpression'}
            fun(node)
            break;
          case 'ClassDeclaration':
            const arr = node.body.body.filter(element =>element.kind === 'constructor')
            let paramsc =  arr[0].value.params.map(x=>x.name)  //node.params.map(x=>x.name)
            
            addToScope(node)
            newScope = new Scope({
              name:node.id.name,
              parent:scope,
              params:paramsc,
            })
            break;
          case 'VariableDeclaration':
            node.declarations.forEach(addToScope)
            break;
          case 'CatchClause':
            scope.add(node.param.name);
            newScope = new Scope({
              name:node.param.name,
              parent:scope,
              params:[node.param.name],
            })
            break;
        }

        if(newScope){
          //如果创建了一个作用域，就添加到node属性里
          // Object.defineProperty(node,'_scope',{value:newScope});
          node._scope = newScope
          scope = newScope;
        }
        
      },
      leave(node,parentNode){
        if(node._scope){
          scope = scope.parent;
        }
      }
    });
  });
  //找出外部依赖 _dependsOn  找出修改的变量
  ast.body.forEach(statement => {
    // 收集变量修改的语句
    function checkForModifies(node) {
      function addNode(n) {
        while (n.type === 'MemberExpression') { // var a = 1; var obj = { c: 3 }; a += obj.c;
          n = n.object
        }
        if (n.type !== 'Identifier') {
          return
        }
        // console.log(n);
        
        statement._modifies[n.name] = true
      }
      if (node.type === 'AssignmentExpression') {
        addNode(node.left)
      } else if (node.type === 'UpdateExpression') { // var a = 1; a++
        addNode(node.argument)
      } else if (node.type === 'CallExpression') {
        node.arguments.forEach(addNode)
      }
    }
    //向上递归
    /**
     * 查找当前作用域链，如果没有找到，代表这个变量是import来的。属于外部变量。
     */
    function checkForDepends(node,parent) {
      if (node.type === 'Identifier') {
        const { name } = node
        
        if(parent.object)return
        else if(parent.type ==='MethodDefinition')return
        else if(parent.type ==='Property')return;
        else if(!name)return;

        // console.log(name);
        // if(node.name ==='visit'){console.log(parent)}
        const definingScope = scope.fundDefingScope(name)
        // 作用域链中找不到 则说明为外部依赖
        // if(node.name =='walk'){console.log(parent,scope)}
        if (!definingScope) {
          // if(node.name ==undefined){console.log(parent,scope)}
          statement._dependsOn[name] = true
        }else{
          if(!scope.names.includes(name)){
            if(!definingScope.parent){
              // console.log(name);
              
              statement._funDefine[name] = true;
            }
          }
        }
        // if(definingScope && statement.type ==='FunctionDeclaration'){
        //   statement._dependsOn[name] = true
        // }
      }
    }
    function checkFun(checkFunReadsNode){
      checkFunReadsNode._walk = true;
      if(checkFunReadsNode.type ==='FunctionDeclaration' 
        || checkFunReadsNode.type ==='FunctionExpression'){
          // if(checkFunReadsNode.id.name ==='walk')console.log(checkFunReadsNode.body.body[0].expression);
          
        function isIdentifier(node,parent){
          // 
          // if(!Array.isArray(node))node.walk = true
          if(Array.isArray(node)){
           node.forEach(nd =>isIdentifier(nd,node)) 
          }if(typeof node === 'object' && node.type ==='Identifier'){
            const { name } = node
            if(name ==='visit')console.log(parent);
            if(scope.names.includes(name)){
              return;
            }else if(parent && parent.object && parent.object.object && parent.object.object.type ==='ThisExpression'){
              return;
            }else{
              const definingScope = scope.fundDefingScope(name);
              // if(name==='fundDefingScope')console.log(checkFunReadsNode);
              if (definingScope) {
                // if(name==='addToScope')console.log(parent,scope.parent);
                //只处理顶级作用域，definingScope.parent === unf 代表已经是顶级作用域
                if(!definingScope.parent){
                  statement._funDefine[name] = true;
                } 
              }
            }
            
          }else{
            if(typeof node === 'object'){
              for(let key in node){
                if(node[key] && typeof node[key] === 'object' && node[key].type){
                  // console.log(node[key]);
                  isIdentifier(node[key],node)
                }
              }
            }
          }
        }
        checkFunReadsNode.body.body.forEach((chindNode)=>{
          isIdentifier(chindNode,checkFunReadsNode)
        })
      }
    }
    // function checkFunDefine(checkFunDefineNode,parent){
    //   if(checkFunDefineNode.type ==='Identifier'){
    //     const { name } = checkFunDefineNode
    //     // if(name==='visit')console.log(parentNode,scope);
    //     if(scope.names.includes(name)){
    //       return;
    //     }else{
    //       const definingScope = scope.fundDefingScope(name);
    //       if (definingScope) {
    //         //只处理顶级作用域，definingScope.parent === unf 代表已经是顶级作用域
    //         if(!definingScope.parent){
    //           statement._funDefine[name] = true;
    //         }
    //       }
    //     }
    //   }
    // }
    walk(statement,{
      enter(node,parentNode){
        if(node._scope){
          scope = node._scope;
        }
        checkForDepends(node,parentNode);
        checkForModifies(node);
        // checkFun(node)
        // checkFunDefine(node,parentNode)
        // Promise.resolve().then(()=>checkFun(node))
      },
      leave(node,parentNode){
        if(node._scope){
          scope = scope.parent;
        }
      }
    })
  });
}